a11y: Track window states more closely
authorMatthias Clasen <mclasen@redhat.com>
Sat, 17 Apr 2021 19:23:04 +0000 (15:23 -0400)
committerEmmanuele Bassi <ebassi@gnome.org>
Mon, 19 Apr 2021 18:22:20 +0000 (19:22 +0100)
Orca ignores events unless the object is inside an object
with role window and states ACTIVE and SHOWING. To arrange
for this, introduce a new ACTIVE platform state, and set it
for windows when they are active.

This gets orca to be a lot more talkative.

gtk/a11y/gtkatspicontext.c
gtk/gtkatcontextprivate.h
gtk/gtkentry.c
gtk/gtkpasswordentry.c
gtk/gtksearchentry.c
gtk/gtkspinbutton.c
gtk/gtktestatcontext.c
gtk/gtkwidget.c
gtk/gtkwindow.c

index a4c15ba41e7eb68adc1200b5a449d092fd7b4a61..9891a4da69094a95e68c2e5e2c46af3c1fd0cf5a 100644 (file)
@@ -150,6 +150,13 @@ collect_states (GtkAtSpiContext    *self,
 
   set_atspi_state (&states, ATSPI_STATE_VISIBLE);
 
+  if (ctx->accessible_role == GTK_ACCESSIBLE_ROLE_WINDOW)
+    {
+      set_atspi_state (&states, ATSPI_STATE_SHOWING);
+      if (gtk_accessible_get_platform_state (accessible, GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE))
+        set_atspi_state (&states, ATSPI_STATE_ACTIVE);
+    }
+
   if (ctx->accessible_role == GTK_ACCESSIBLE_ROLE_TEXT_BOX ||
       ctx->accessible_role == GTK_ACCESSIBLE_ROLE_SEARCH_BOX ||
       ctx->accessible_role == GTK_ACCESSIBLE_ROLE_SPIN_BUTTON)
@@ -888,6 +895,7 @@ gtk_at_spi_context_state_change (GtkATContext                *ctx,
       if (GTK_IS_ROOT (accessible))
         {
           gtk_at_spi_root_child_changed (self->root, change, accessible);
+          emit_state_changed (self, "showing", gtk_boolean_accessible_value_get (value));
         }
       else
         {
@@ -1084,6 +1092,13 @@ gtk_at_spi_context_platform_change (GtkATContext                *ctx,
                                                           GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED);
       emit_state_changed (self, "focused", state);
     }
+
+  if (changed_platform & GTK_ACCESSIBLE_PLATFORM_CHANGE_ACTIVE)
+    {
+      gboolean state = gtk_accessible_get_platform_state (GTK_ACCESSIBLE (widget),
+                                                          GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE);
+      emit_state_changed (self, "active", state);
+    }
 }
 
 static void
index d9678cbea56d0c0c1162196862089e0ab3ddf410..c05c04948f3168d24f24ad62b959a6003725bec7 100644 (file)
@@ -83,11 +83,13 @@ typedef enum {
 typedef enum {
   GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE,
   GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED,
+  GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE
 } GtkAccessiblePlatformState;
 
 typedef enum {
   GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSABLE = 1 << GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE,
   GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSED   = 1 << GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED,
+  GTK_ACCESSIBLE_PLATFORM_CHANGE_ACTIVE    = 1 << GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE,
 } GtkAccessiblePlatformChange;
 
 typedef enum {
index 8a1262bf14d16c3ff932c68896fa48bd21c4a8ad..e5a4de82553f7a3028b2c4a16e85346569024920 100644 (file)
@@ -351,6 +351,8 @@ gtk_entry_accessible_get_platform_state (GtkAccessible              *self,
       return gtk_widget_get_focusable (GTK_WIDGET (priv->text));
     case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED:
       return gtk_widget_has_focus (GTK_WIDGET (priv->text));
+    case GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE:
+      return FALSE;
     default:
       g_assert_not_reached ();
     }
index 8096299fb55082e2771e7e0fbb75378af11a5b5c..32eacc865bc9cbe2ad8ac7cb2907429e2560e061 100644 (file)
@@ -532,6 +532,8 @@ gtk_password_entry_accessible_get_platform_state (GtkAccessible              *se
       return gtk_widget_get_focusable (GTK_WIDGET (entry->entry));
     case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED:
       return gtk_widget_has_focus (GTK_WIDGET (entry->entry));
+    case GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE:
+      return FALSE;
     default:
       g_assert_not_reached ();
     }
index 64827efdf49bc605b1bb215acde482183c01e21e..255bd018e5d0e0938e8b1505104fc7c62f29535c 100644 (file)
@@ -475,6 +475,8 @@ gtk_search_entry_accessible_get_platform_state (GtkAccessible              *self
       return gtk_widget_get_focusable (GTK_WIDGET (entry->entry));
     case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED:
       return gtk_widget_has_focus (GTK_WIDGET (entry->entry));
+    case GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE:
+      return FALSE;
     default:
       g_assert_not_reached ();
     }
index 6030261cd44c85de1c4c5f8362990ff61665765d..344f8870e63a0d5ce387f524ca62f5c0fce240a9 100644 (file)
@@ -633,6 +633,8 @@ gtk_spin_button_accessible_get_platform_state (GtkAccessible              *self,
       return gtk_widget_get_focusable (spin_button->entry);
     case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED:
       return gtk_widget_has_focus (spin_button->entry);
+    case GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE:
+      return FALSE;
     default:
       g_assert_not_reached ();
     }
index a093fe62226d55cf4f229e7addc7995e0d34f85c..e8f3754ea9b375982e3e035038d2e8f5bee6b208 100644 (file)
@@ -96,6 +96,9 @@ gtk_test_at_context_platform_change (GtkATContext                *self,
       if (changed_platform & GTK_ACCESSIBLE_PLATFORM_CHANGE_FOCUSED)
         g_print ("***    focused = %d\n",
                  gtk_accessible_get_platform_state (accessible, GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED));
+      if (changed_platform & GTK_ACCESSIBLE_PLATFORM_CHANGE_ACTIVE)
+        g_print ("***    active = %d\n",
+                 gtk_accessible_get_platform_state (accessible, GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE));
     }
 }
 
index 3f641a6d08d6360c6bf1cddab8dbd5405413a9c4..b9088cd3efaf9b6834c25ac3d5135397c4d62fb1 100644 (file)
@@ -8492,6 +8492,8 @@ gtk_widget_accessible_get_platform_state (GtkAccessible              *self,
       return gtk_widget_get_focusable (GTK_WIDGET (self));
     case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED:
       return gtk_widget_has_focus (GTK_WIDGET (self));
+    case GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE:
+      return FALSE;
     default:
       g_assert_not_reached ();
     }
index 17beb19fa364302e1b4968e20afc6031f9941d2d..b8ea6e3e219c707c5923f17338f3819560321176 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "gtkwindowprivate.h"
 
+#include "gtkaccessibleprivate.h"
 #include "gtkaccelgroupprivate.h"
 #include "gtkactionable.h"
 #include "gtkapplicationprivate.h"
@@ -479,6 +480,9 @@ static void             gtk_window_shortcut_manager_interface_init      (GtkShor
 static void             gtk_window_root_interface_init (GtkRootInterface *iface);
 static void             gtk_window_native_interface_init  (GtkNativeInterface  *iface);
 
+static void             gtk_window_accessible_interface_init (GtkAccessibleInterface *iface);
+
+
 static void ensure_state_flag_backdrop (GtkWidget *widget);
 static void unset_titlebar (GtkWindow *window);
 
@@ -493,6 +497,8 @@ gtk_window_update_csd_size (GtkWindow *window,
 
 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_WIDGET,
                          G_ADD_PRIVATE (GtkWindow)
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ACCESSIBLE,
+                                               gtk_window_accessible_interface_init)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
                                                gtk_window_buildable_interface_init)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_NATIVE,
@@ -502,6 +508,32 @@ G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_WIDGET,
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_ROOT,
                                                gtk_window_root_interface_init))
 
+static GtkAccessibleInterface *parent_accessible_iface;
+
+static gboolean
+gtk_window_accessible_get_platform_state (GtkAccessible              *self,
+                                          GtkAccessiblePlatformState  state)
+{
+  switch (state)
+    {
+    case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSABLE:
+    case GTK_ACCESSIBLE_PLATFORM_STATE_FOCUSED:
+      return parent_accessible_iface->get_platform_state (self, state);
+    case GTK_ACCESSIBLE_PLATFORM_STATE_ACTIVE:
+      return gtk_window_is_active (GTK_WINDOW (self));
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+gtk_window_accessible_interface_init (GtkAccessibleInterface *iface)
+{
+  parent_accessible_iface = g_type_interface_peek_parent (iface);
+  iface->get_at_context = parent_accessible_iface->get_at_context;
+  iface->get_platform_state = gtk_window_accessible_get_platform_state;
+}
+
 static void
 add_tab_bindings (GtkWidgetClass   *widget_class,
                  GdkModifierType   modifiers,
@@ -5828,6 +5860,8 @@ _gtk_window_set_is_active (GtkWindow *window,
       g_object_unref (focus);
     }
 
+  gtk_accessible_platform_changed (GTK_ACCESSIBLE (window), GTK_ACCESSIBLE_PLATFORM_CHANGE_ACTIVE);
+
   g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_IS_ACTIVE]);
 }